﻿using Nirvana;
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using UnityEditor;
using UnityEngine;

public abstract class CustomShaderGUI : ShaderGUI {

    private bool isok = true;
    [StructLayout(LayoutKind.Sequential, Size = 1)]
    public struct ShaderOption
    {
        public string Key { get; set; }
        public GUIContent Content { get; set; }
        private string _str;
        private GUIContent _guiContent;
    }

    protected abstract void FindProperties(MaterialProperty[] properties);
    protected abstract void OnShaderGUI(MaterialEditor materialEditor, Material[] materials);
    protected virtual void MaterialChanged(Material material) { }


    public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties)
    {
        this.FindProperties(properties);
        Material[] array = new Material[materialEditor.targets.Length];
        for (int i = 0; i < materialEditor.targets.Length; i++)
        {
            array[i] = (Material)materialEditor.targets[i];
        }
        bool change_flag = false;
        EditorGUI.BeginChangeCheck();
        this.OnShaderGUI(materialEditor, array);
        if (EditorGUI.EndChangeCheck())
        {
            change_flag = true;
        }
        if ((Event.current.type == EventType.ValidateCommand || Event.current.type == EventType.ExecuteCommand)
    && Event.current.commandName == "UndoRedoPerformed")
        {
            change_flag = true;
        }
        //清除场景上记录过变体的mat数据，以便刷新新设置的mat
        if (change_flag) RendererMaterialCache.ClearCache();

        if (this.isok)
        {
            foreach (Material material in array)
            {
                this.MaterialChanged(material);
            }
            this.isok = false;
        }

    }

    public override void AssignNewShaderToMaterial(Material material, Shader oldShader, Shader newShader)
    {
        base.AssignNewShaderToMaterial(material, oldShader, newShader);
        if (oldShader == null)
        {
            return;
        }
        this.MaterialChanged(material);
    }
    protected bool HasKeyword(Material[] materials, string key)
    {
        return Array.IndexOf<string>(materials[0].shaderKeywords, key) != -1;
    }

    protected bool HasAnyKeywords(Material[] materials, params string[] keys)
    {
        foreach (string text in keys)
        {
            int num = Array.IndexOf<string>(materials[0].shaderKeywords, text);
            if (num != -1)
            {
                return true;
            }
        }
        return false;
    }

    protected bool CheckOption(Material[] materials, string content, string key)
    {
        return this.CheckOption(materials, new GUIContent(content), key);
    }

    protected bool CheckOption(Material[] materials, string content, params string[] keys)
    {
        return this.CheckOption(materials, new GUIContent(content), keys);
    }


    protected bool CheckOption(Material[] materials, GUIContent content, string key)
    {
        bool flag = this.HasKeyword(materials, key);
        EditorGUI.BeginChangeCheck();
        flag = EditorGUILayout.ToggleLeft(content, flag, new GUILayoutOption[0]);
        if (EditorGUI.EndChangeCheck())
        {
            if (flag)
            {
                foreach (Material material in materials)
                {
                    material.EnableKeyword(key);
                }
            }
            else
            {
                foreach (Material material2 in materials)
                {
                    material2.DisableKeyword(key);
                }
            }
        }
        return flag;
    }


    protected bool CheckOption(Material[] materials, GUIContent content, params string[] keys)
    {
        bool flag = this.HasAnyKeywords(materials, keys);
        EditorGUI.BeginChangeCheck();
        flag = EditorGUILayout.ToggleLeft(content, flag, new GUILayoutOption[0]);
        if (EditorGUI.EndChangeCheck())
        {
            string keyword = keys[0];
            if (flag)
            {
                foreach (Material material in materials)
                {
                    material.EnableKeyword(keyword);
                }
            }
            else
            {
                foreach (string keyword2 in keys)
                {
                    foreach (Material material2 in materials)
                    {
                        material2.DisableKeyword(keyword2);
                    }
                }
            }
        }
        return flag;
    }

    protected bool SwitchOption(Material[] materials, string content, string keyEnable, string keyDisable)
    {
        return this.SwitchOption(materials, new GUIContent(content), keyEnable, keyDisable);
    }


    protected bool SwitchOption(Material[] materials, GUIContent content, string keyEnable, string keyDisable)
    {
        bool flag = this.HasKeyword(materials, keyEnable);
        EditorGUI.BeginChangeCheck();
        flag = EditorGUILayout.ToggleLeft(content, flag, new GUILayoutOption[0]);
        if (EditorGUI.EndChangeCheck())
        {
            if (flag)
            {
                foreach (Material material in materials)
                {
                    material.EnableKeyword(keyEnable);
                    material.DisableKeyword(keyDisable);
                }
            }
            else
            {
                foreach (Material material2 in materials)
                {
                    material2.EnableKeyword(keyDisable);
                    material2.DisableKeyword(keyEnable);
                }
            }
        }
        return flag;
    }


    protected int ListOptions(Material[] materials, GUIContent[] contents, string[] keys, bool toolbar = false)
    {
        int num = -1;
        foreach (string text in materials[0].shaderKeywords)
        {
            num = Array.IndexOf<string>(keys, text);
            if (num >= 0)
            {
                break;
            }
        }
        if (num < 0)
        {
            num = Array.IndexOf<string>(keys, "_");
        }
        if (num < 0)
        {
            num = Array.IndexOf<string>(keys, "__");
        }
        EditorGUI.BeginChangeCheck();
        if (toolbar)
        {
            num = GUILayout.Toolbar(num, contents, new GUILayoutOption[0]);
        }
        else
        {
            num = EditorGUILayout.Popup(num, contents, new GUILayoutOption[0]);
        }
        if (EditorGUI.EndChangeCheck())
        {
            string text2 = keys[num];
            foreach (Material material in materials)
            {
                foreach (string keyword in keys)
                {
                    material.DisableKeyword(keyword);
                }
            }
            if (text2 != "_" && text2 != "__")
            {
                foreach (Material material2 in materials)
                {
                    material2.EnableKeyword(text2);
                }
            }
        }
        return num;
    }


    protected bool TextureGUIWithKeyword(MaterialEditor materialEditor, Material[] materials, MaterialProperty prop, string label, string keyword)
    {
        return this.TextureGUIWithKeyword(materialEditor, materials, prop, new GUIContent(label), keyword);
    }

    protected bool TextureGUIWithKeyword(MaterialEditor materialEditor, Material[] materials, MaterialProperty prop, GUIContent label, string keyword)
    {
        EditorGUI.BeginChangeCheck();
        materialEditor.TexturePropertySingleLine(label, prop);
        if (EditorGUI.EndChangeCheck())
        {
            foreach (Material material in materials)
            {
                if (prop.textureValue != null)
                {
                    material.EnableKeyword(keyword);
                }
                else
                {
                    material.DisableKeyword(keyword);
                }
            }
        }
        return prop.textureValue != null;
    }

    protected void ChangeShader(MaterialEditor materialEditor, Material[] materials, string shaderName)
    {
        Shader shader = Shader.Find(shaderName);
        if (shader == null)
        {
            Debug.LogError("Can not find shader: " + shaderName);
            return;
        }
        materialEditor.RegisterPropertyChangeUndo("Change Shader: " + shaderName);
        foreach (Material material in materials)
        {
            material.shader = shader;
        }
    }



}
